package com.norns.torque.bluetooth

import android.annotation.SuppressLint
import android.app.Application
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothDevice.TRANSPORT_LE
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattService
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.BluetoothLeAdvertiser
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.norns.torque.entrty.DeviceConnectionState
import com.norns.torque.entrty.Message
import com.norns.torque.entrty.WifiDevice
import com.norns.torque.listener.BluetoothRssiListener
import com.norns.torque.listener.BluetoothStateListener
import com.norns.torque.listener.ConnectedListener
import com.norns.torque.listener.MessageListener
import com.norns.torque.network.NetworkListenerHelper.NetworkConnectedListener
import com.norns.torque.socket.ClientSocket
import com.norns.torque.utils.AppConstant
import com.norns.torque.utils.AppContext
import com.norns.torque.utils.DataConversion
import timber.log.Timber
import java.util.LinkedList
import java.util.UUID


object ChatServer {
    private var read_UUID_chara: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")
    private var read_UUID_service: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")

    private var write_UUID_chara: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")
    private var write_UUID_service: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")

    private var notify_UUID_chara: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")
    private var notify_UUID_service: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")

    private var indicate_UUID_chara: UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")
    private var indicate_UUID_service: UUID =
        UUID.fromString("00001800-0000-1000-8000-00805f9b34fb")

    var connectedState: Int = -1

    const val ReadRSSI: Int = 789

    const val Bluetooth = 0
    const val NetWork = 1
    var contentType: Int = 0
    private val messageList = ArrayList<String>()
    //连接设备
    private val _contentDevice = MutableLiveData<WifiDevice>()
    val contentDevice = _contentDevice as LiveData<WifiDevice>

    private var gattClient: BluetoothGatt? = null
    private var gattClientCallback: BluetoothGattCallback? = null

    // Properties for current chat device connection
    var currentDevice: BluetoothDevice? = null
    private var messageCharacteristic: BluetoothGattCharacteristic? = null

    private var mRssiListenerList: ArrayList<BluetoothRssiListener> = ArrayList()
    private var mMessageListenerList: ArrayList<MessageListener> = ArrayList()
    private var mConnectedListener: ArrayList<ConnectedListener> = ArrayList()
    private var mBluetoothStateListener: ArrayList<BluetoothStateListener> = ArrayList()

    //Rssi监听
    fun addBluetoothRssiListener(listener: BluetoothRssiListener) {
        mRssiListenerList.add(listener)
    }

    //连接状态监听
    fun addConnectionListener(listener: ConnectedListener) {
        mConnectedListener.add(listener)
    }

    //蓝牙状态监听器
    fun addBluetoothStateListener(listener: BluetoothStateListener) {
        mBluetoothStateListener.add(listener)
    }

    //消息监听
    fun addMessagesListener(listener: MessageListener) {
        mMessageListenerList.add(listener)
    }

    fun removeConnectionListener(listener: ConnectedListener) {
        if (mConnectedListener.isNotEmpty()) {
            mConnectedListener.remove(listener)
        }
    }

    fun removeBluetoothRssiListener(listener: BluetoothRssiListener) {
        if (mRssiListenerList.isNotEmpty()) {
            mRssiListenerList.remove(listener)
        }
    }

    fun removeBluetoothStateListener(listener: BluetoothStateListener) {
        if (mBluetoothStateListener.isNotEmpty()) {
            mBluetoothStateListener.remove(listener)
        }
    }

    fun removeMessagesListener(listener: MessageListener) {
        if (mMessageListenerList.isNotEmpty()) {
            mMessageListenerList.remove(listener)
        }
    }
    fun addMessage(message:String){
        messageList.add(message)
    }
    fun getMessageList():ArrayList<String>{
        return messageList
    }
    fun clearMessage(){
        messageList.clear()
    }
    private var isRssiResult: Boolean = false

    //连续5次没有返回 代表连接已断开
    private var rssiResultCount: Int = 0

    fun initHandler() {
        mHandlerThread = HandlerThread("TimeHandlerThread").also { it.start() }
        mHandler = object : Handler(mHandlerThread!!.getLooper()) {
            @SuppressLint("MissingPermission")
            override fun handleMessage(msg: android.os.Message) {
                if (msg.what == ReadRSSI) {
                    if (rssiResultCount > 6) {
                        Timber.i("设备已断开连接")
                        setContentState(AppConstant.connectionField)
                    } else if (connectedState == AppConstant.connectionSuccess) {
                        if (!isRssiResult) {
                            rssiResultCount += 1
                        }
                        gattClient?.readRemoteRssi()
                        isRssiResult = false
                        sendEmptyMessageDelayed(ReadRSSI, 5000)
                    }
                }
            }
        }
    }

    fun setContentState(state: Int) {
        connectedState = state
        if (mConnectedListener.isNotEmpty()) {
            mConnectedListener.forEach { listener ->
                listener.onConnected(state)
            }
        }
    }

    @SuppressLint("MissingPermission")
    fun setCurrentChatConnection(device: BluetoothDevice) {
        disconnect(true)
        currentDevice = device
        _contentDevice.value = WifiDevice(device.name ?: "Unknown", device.address, 0)
        contentType = Bluetooth
        connectToChatDevice(device)
    }

    @SuppressLint("MissingPermission")
    private fun connectToChatDevice(device: BluetoothDevice) {
        setContentState(AppConstant.connectionStart)
        //连接蓝牙设备
        gattClientCallback = GattClientCallback()
        gattClient = device.connectGatt(AppContext.context, false, gattClientCallback, TRANSPORT_LE)
        //gattClient = device.connectGatt(AppContext.context, false, gattClientCallback)
    }

    @SuppressLint("MissingPermission")
    fun sendMessage(message: String) {
        Timber.d("  向设备发送数据: ${message}")
        val data = DataConversion.hexStringToByteArray(message)
        if (data.size > 20) { //数据大于个字节 分批次写入
            Timber.e("writeData: length=" + data.size)
            var num = 0
            num = if (data.size % 20 != 0) {
                data.size / 20 + 1
            } else {
                data.size / 20
            }
            for (i in 0 until num) {
                var tempArr: ByteArray
                if (i == num - 1) {
                    tempArr = ByteArray(data.size - i * 20)
                    System.arraycopy(data, i * 20, tempArr, 0, data.size - i * 20)
                } else {
                    tempArr = ByteArray(20)
                    System.arraycopy(data, i * 20, tempArr, 0, 20)
                }
                sendMessage(tempArr)
            }
        } else {
            sendMessage(data)
        }
    }

    fun sendByteArrayMessage(messageBytes: ByteArray) {
        sendMessage(messageBytes)
//        if (messageBytes.size > 20) { //数据大于个字节 分批次写入
//            Timber.e("设备writeData: length=" + messageBytes.size)
//            var num = 0
//            num = if (messageBytes.size % 20 != 0) {
//                messageBytes.size / 20 + 1
//            } else {
//                messageBytes.size / 20
//            }
//            for (i in 0 until num) {
//                var tempArr: ByteArray
//                if (i == num - 1) {
//                    tempArr = ByteArray(messageBytes.size - i * 20)
//                    System.arraycopy(messageBytes, i * 20, tempArr, 0, messageBytes.size - i * 20)
//                } else {
//                    tempArr = ByteArray(20)
//                    System.arraycopy(messageBytes, i * 20, tempArr, 0, 20)
//                }
//                sendMessage(tempArr)
//            }
//        } else {
//            sendMessage(messageBytes)
//        }
    }

    @SuppressLint("MissingPermission")
    fun sendMessage(messageBytes: ByteArray) {
        messageCharacteristic?.let { characteristic ->
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                val success = gattClient?.writeCharacteristic(
                    characteristic,
                    messageBytes,
                    BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
                )
            } else {
                //characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
                characteristic.value = messageBytes
                val success = gattClient?.writeCharacteristic(characteristic) ?: false
                Timber.d("onServicesDiscovered22: message send: $success")
            }
        }
    }

    private class GattClientCallback : BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            val isSuccess = status == BluetoothGatt.GATT_SUCCESS
            val isConnected = newState == BluetoothProfile.STATE_CONNECTED
            Timber.d("onConnectionStateChange: Client $gatt  success: $isSuccess connected: $isConnected")
            // try to send a message to the other device as a test
            if (isSuccess && isConnected) {
                // discover services
                //发现服务
                //连接成功，开始搜索服务，一定要调用此方法，否则获取不到服务
                gatt.discoverServices()
                setContentState(AppConstant.connectionIng)
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                //已断开连接
                Timber.i("设备已断开连接")
                setContentState(AppConstant.connectionField)
            }
        }

        @SuppressLint("MissingPermission")
        override fun onServicesDiscovered(discoveredGatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(discoveredGatt, status)
            //发现服务 回调
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Timber.d("onServicesDiscovered: Have gatt $discoveredGatt")
                if (null != discoveredGatt) {
                    initServiceAndChara(discoveredGatt)
                    //获取指定GATT服务，UUID 由远程设备提供
                    //订阅通知
                    val characteristic = discoveredGatt.getService(notify_UUID_service)
                        .getCharacteristic(notify_UUID_chara)
                    gattClient!!.setCharacteristicNotification(characteristic, true)
                    //获取指定GATT特征，UUID 由远程设备提供
                    messageCharacteristic = discoveredGatt.getService(write_UUID_service)
                        .getCharacteristic(write_UUID_chara)
                    setContentState(AppConstant.connectionSuccess)
                }
            }
        }

        @SuppressLint("MissingPermission")
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            Timber.e("onCharacteristicWrite()  status=${status}")
        }

        override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
            super.onReadRemoteRssi(gatt, rssi, status)
            isRssiResult = true
            Timber.d("接收到设备返回的RSSI: $rssi")
            mRssiListenerList.forEach { listener ->
                listener.onRssi(rssi)
            }
        }

        /**
         * 接收到硬件返回的数据
         * */
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray
        ) {
            super.onCharacteristicChanged(gatt, characteristic, value)
            val hexStr = DataConversion.encodeHexString(value)
            Timber.d("接收到设备返回的数据: $hexStr")
            if (mMessageListenerList.isNotEmpty()) {
                mMessageListenerList.last().onMessage(hexStr)
            }
        }

        override fun onCharacteristicChanged(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
                characteristic?.let { characteristic ->
                    val hexStr = DataConversion.encodeHexString(characteristic.value)
                    Timber.d("接收到设备返回的数据222: $hexStr")
                    if (mMessageListenerList.isNotEmpty()) {
                        mMessageListenerList.last().onMessage(hexStr)
                    }
                }
            }

        }
    }


    private fun initServiceAndChara(discoveredGatt: BluetoothGatt) {
        val bluetoothGattServices: List<BluetoothGattService> = discoveredGatt.getServices()
        for (bluetoothGattService in bluetoothGattServices) {
            val characteristics = bluetoothGattService.characteristics
            for (characteristic in characteristics) {
                val charaProp = characteristic.properties
                if ((charaProp and BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    read_UUID_chara = characteristic.uuid
                    read_UUID_service = bluetoothGattService.uuid
                    Timber.i("read_chara=$read_UUID_chara----read_service=$read_UUID_service")
                }
                if ((charaProp and BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    write_UUID_chara = characteristic.uuid
                    write_UUID_service = bluetoothGattService.uuid
                    Timber.i("write_chara=$write_UUID_chara----write_service=$write_UUID_service")
                }
//                if ((charaProp and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
//                     write_UUID_chara = characteristic.uuid
//                     write_UUID_service = bluetoothGattService.uuid
//                    Timber.i("write_chara=$write_UUID_chara----write_service=$write_UUID_service")
//                }
//                if ((charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
//                    notify_UUID_chara = characteristic.uuid
//                    notify_UUID_service = bluetoothGattService.uuid
//                    Timber.i("notify_chara=$notify_UUID_chara----notify_service=$notify_UUID_service")
//                }
                if ((charaProp and BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
                    //indicate_UUID_chara = characteristic.uuid
                    notify_UUID_chara = characteristic.uuid
                    //indicate_UUID_service = bluetoothGattService.uuid
                    notify_UUID_service = bluetoothGattService.uuid
                    Timber.i("indicate_chara=$indicate_UUID_chara----indicate_service=$indicate_UUID_service")
                }
            }
        }
    }

    @SuppressLint("MissingPermission")
    fun disconnect(isFirst: Boolean = false) {
        mHandlerThread?.interrupt()
        mHandler?.removeCallbacksAndMessages(null)
        if (!isFirst) {
            setContentState(AppConstant.connectionNone)
        }
        gattClient?.disconnect()
    }


    fun bluetoothOff() {
        Timber.d("蓝牙已关闭${contentType}")
        if (contentType == Bluetooth) {
            mBluetoothStateListener.forEach { listener ->
                listener.onState(BluetoothAdapter.STATE_OFF)
            }
        }
    }

    fun bluetoothOpen() {
        Timber.d("蓝牙已打开${contentType}")
        if (contentType == Bluetooth) {
            mBluetoothStateListener.forEach { listener ->
                listener.onState(BluetoothAdapter.STATE_ON)
            }
        }
    }

    fun setContentDevice(device: WifiDevice, type: Int) {
        contentType = type
        _contentDevice.value = device
    }

    fun updateBluetoothName(bluetoothName: String) {
        val wifiDevice: WifiDevice? = _contentDevice.value
        wifiDevice?.let { device ->
            device.name = bluetoothName
            _contentDevice.value = device
        }
    }

    //自动连接
    fun autoConnection() {
        if (contentType == Bluetooth) {
            if (null != currentDevice) {
                connectToChatDevice(currentDevice!!)
            }
        }
    }

    private var mHandlerThread: HandlerThread? = null
    private var mHandler: Handler? = null

    //不间断获取rssi
    fun startGetDeviceRssi() {
        if (contentType == Bluetooth) {
            mHandler?.let { handler ->
                rssiResultCount = 0
                handler.removeMessages(ReadRSSI)
                handler.sendEmptyMessageDelayed(ReadRSSI, 1000)
            }
        }
    }

    fun stopGetDeviceRssi() {
        if (contentType == Bluetooth) {
            mHandler?.let { handler ->
                rssiResultCount = 0
                handler.removeMessages(ReadRSSI)
            }
        }
    }
}